﻿Yxcm.Map = {};

Yxcm.Map.Style = {
    point: { lineColor: '#00ff00', lineThickness: 3, lineOpacity: 100, backgroundColor: '#ffffff', backgroundOpacity: 50, icon: '/pub/share/css/map/images/balloon.gif' },
    line: { lineColor: '#436c83', lineThickness: 3, lineOpacity: 100, backgroundColor: '#ffffff', backgroundOpacity: 50, icon: '/pub/share/css/map/images/line_balloon.gif' },
    area: { lineColor: '#00ff00', lineThickness: 3, lineOpacity: 100, backgroundColor: '#ffffff', backgroundOpacity: 50, icon: '/pub/share/css/map/images/area_balloon.gif' }
};

Yxcm.Map.PointMarker = function() {
    this.relationalMarker = null;
    this.detailIsShowing = false;
    this.type = "point";
    this.map = null;
    this.title = '';
    this.style = null;
    this.id = null;
    this.coordinate = null;
    this.detailContainer = null;
    this.marker = null;
    this.isHidden = false;
    this.contextMenu = null;
    this.dragging = false;
    Yxcm.Map.PointMarker.superclass.constructor.apply(this, arguments);
};
Yxcm.extend(Yxcm.Map.PointMarker, Yxcm.Event, {

    initialize: function(config) {
        this.detailIsShowing = false;
        this.map = config.map;
        this.title = config.title;
        this.style = jQuery.extend({}, Yxcm.Map.Style.point, config.style);
        this.id = config.id;
        this.coordinate = config.coordinates[0];
        this.detailContainer = jQuery('<div class="detail-container"></div>');
        this.contextMenuObject = null;
        this.draw();
    },

    draw: function() {
        if (this.marker) {
            this.marker.destroy();
        }
        this.marker = this.map.maplet.addBalloonMarker(this.coordinate, 1000, this.style.icon, this.title, null, null);
        jQuery(this.marker.div).append(this.detailContainer);
        jQuery(this.marker.img).bind('mouseout.onShowTitle', Yxcm.setScope(this.onShowTitle, this));
        jQuery(this.marker.img).bind('click.onClick', Yxcm.setScope(this.onClick, this));
    },

    setTitle: function(value) {
        this.title = value;
        this.marker.setTitle(this.title);
    },

    showTitle: function() {
        jQuery(this.marker.img).mouseover();
    },

    hideTitle: function() {
        jQuery(this.marker.img).mouseout();
    },

    setDetail: function(content) {
        this.detailContainer.html(content).pngFix();
        var offset = this.detailContainer.offset();
        var h = this.detailContainer.height();
        var w = this.detailContainer.width();
        var adjustH = jQuery(this.marker.img).height();
        this.detailContainer.css({ left: -(w / 2), top: -h - adjustH });
    },

    showDetail: function() {
        jQuery(this.marker.div).css('z-index', 599999);
        this.notifyEvent('beforeShowDetail', { sender: this });
        this.map.moveTo(this.coordinate);
        this.detailContainer.show();
        this.detailIsShowing = true;
        this.disableContextMenu();
        this.notifyEvent('afterShowDetail', { sender: this });
    },

    hideDetail: function() {
        jQuery(this.marker.div).css('z-index', 1000);
        this.detailIsShowing = false;
        this.detailContainer.hide();
        this.enableContextMenu();
    },

    clearDetail: function() {
        this.hideDetail();
        this.detailContainer.empty();
    },

    show: function() {
        this.marker.show();
        if (this.referenceMarker) {
            this.referenceMarker.show();
        }
        this.isHidden = false;
    },

    hide: function() {
        this.marker.hide();
        this.clearDetail();
        if (this.referenceMarker) {
            this.referenceMarker.hide();
        }
        this.isHidden = true;
    },

    destroy: function() {
        this.notifyEvent('beforeDestroy', { sender: this });
        this.detailContainer.empty();
        this.marker.destroy();
        if (this.referenceMarker) {
            this.referenceMarker.destroy();
        }
        this.notifyEvent('afterDestroy', { sender: this });
    },

    enableContextMenu: function() {
        if (this.contextMenu) {
            jQuery(this.marker.div).contextMenu({ menu: this.contextMenu }, Yxcm.setScope(this.onContextMenu, this));
            jQuery(this.marker.div).enableContextMenu();
        }
    },

    disableContextMenu: function() {
        if (this.contextMenu) {
            jQuery(this.marker.div).disableContextMenu();
        }
    },

    enableContextMenuItems: function() {
        var args = arguments;
        for (var i = 0; i < args.length; i++) {
            jQuery(this.marker.div).enableContextMenuItems(args[i]);
        }
    },

    disableContextMenuItems: function() {
        var args = arguments;
        for (var i = 0; i < args.length; i++) {
            jQuery(this.marker.div).disableContextMenuItems('#' + args[i]);
        }
    },

    startDrag: function() {
        if (!this.referenceMarker) {
            jQuery(this.marker.div).draggable({ opacity: 0.5 });
        }
        if (this.marker.balloonlabel) {
            this.marker.balloonlabel.hide();
            this.marker.balloonlabel = null;
        }
        this.detailContainer.empty();
        this.dragging = true;
        this.notifyEvent('startDrag', { sender: this });
    },

    stopDrag: function(position) {
        jQuery(this.marker.div).draggable('destroy');
        this.detailContainer.empty();
        this.marker.destroy();
        this.draw();
        this.map.refresh();
        this.dragging = false;
        if (this.contextMenu) {
            this.contextMenu = 'pointMenu';
            this.enableContextMenu();
            this.disableContextMenuItems('stopDrag', 'cancelDrag');
        }
        this.notifyEvent('stopDrag', { sender: this });
    },

    cancelDrag: function() {
        this.detailContainer.empty();
        this.marker.destroy();
        this.draw();
        this.map.refresh();
        this.dragging = false;
        if (this.contextMenu) {
            this.contextMenu = 'pointMenu';
            this.enableContextMenu();
            this.disableContextMenuItems('stopDrag', 'cancelDrag');
        }
        this.notifyEvent('cancelDrag', { sender: this });
    },

    onContextMenu: function(action, el, pos) {
        this.notifyEvent('clickContextMenu', { action: action, sender: this, position: pos });
    },

    onShowTitle: function() {
        if (this.detailIsShowing) {
            jQuery(this.marker.div).css('z-index', 599999);
        }
    },

    onClick: function() {
        if (!this.dragging) {
            this.notifyEvent('click', { sender: this });
        }
    }
});

Yxcm.Map.LineMarker = function() {
    this.detailIsShowing = false;
    this.type = "line";
    this.map = null;
    this.title = '';
    this.style = null;
    this.id = null;
    this.coordinates = [];
    this.detailContainer = null;
    this.marker = null;
    this.points = [];
    this.showStartPoint = true;
    this.showEndPoint = false;
    Yxcm.Map.LineMarker.superclass.constructor.apply(this, arguments);
};
Yxcm.extend(Yxcm.Map.LineMarker, Yxcm.Event, {

    initialize: function(config) {
        this.map = config.map;
        this.title = config.title;
        this.style = jQuery.extend({}, Yxcm.Map.Style.line, config.style);
        this.id = config.id;
        this.coordinates = config.coordinates;
        this.marker = null;
        this.draw();
    },

    draw: function() {
        if (this.marker) {
            this.marker.destroy();
        }
        var innerOpacity = this.style.lineOpacity;
        if ($.browser.mozilla) {
            innerOpacity = innerOpacity / 100;
        }
        this.marker = this.map.maplet.addStaticPathMarker(this.coordinates, this.style.lineColor, this.style.lineThickness, innerOpacity);
        this.map.maplet.refreshMarkers();
        this.map.maplet.refreshStaticMarkers();
    },

    redraw: function() {
        if (this.marker) {
            this.destroy();
        }
        this.draw();
    },

    show: function() {
        jQuery(this.marker.div).show();
        this.isHidden = false;
    },

    hide: function() {
        jQuery(this.marker.div).hide();
        this.isHidden = true;
    },

    destroy: function() {
        this.marker.destroy();
    }
});

Yxcm.Map.AreaMarker = function() {
    this.detailIsShowing = false;
    this.type = "area";
    this.map = null;
    this.title = '';
    this.style = null;
    this.id = null;
    this.coordinates = [];
    this.detailContainer = null;
    this.marker = null;
    Yxcm.Map.LineMarker.superclass.constructor.apply(this, arguments);
};
Yxcm.extend(Yxcm.Map.AreaMarker, Yxcm.Event, {

    initialize: function(config) {
        this.map = config.map;
        this.title = config.title;
        this.style = jQuery.extend({}, Yxcm.Map.Style.area, config.style);
        this.id = config.id;
        this.coordinates = config.coordinates;
        this.marker = null;
        this.draw();
    },

    draw: function() {
        var innerOpacity = this.style.lineOpacity;
        if ($.browser.mozilla) {
            innerOpacity = innerOpacity / 100;
        }
        this.marker = this.map.maplet.addStaticRegionMarker(this.coordinates,
            this.style.lineColor, this.style.backgroundColor, this.style.lineThickness);
    },

    redraw: function() {
        if (this.marker) {
            this.destroy();
        }
        this.draw();
    },

    show: function() {
        jQuery(this.marker.div).show();
        this.isHidden = false;
    },

    hide: function() {
        jQuery(this.marker.div).hide();
        this.isHidden = true;
    },

    destroy: function() {
        this.marker.destroy();
    }
});

var currentMap = null;
Yxcm.Map.Map = function() {
    currentMap = this;
    this.markers = [];
    this.activeMarker = null;
    this.lineBrush = null;
    this.areaBrush = null;
    this.isDrawing = false;
    this.mouseClickTrack = [];
    this.isMouseClickTrack = false;
    this.mouseMoveTrack = [];
    this.isMouseMoveTrack = false;
    this.autoScroll = false;
    this.brushType = '';
    this.eventHandlers = [];
    this.tempEventObj = { isLock: true };
    this.contextMenu = null;

    this.eventListener = {
        line: {
            onsuccess: function() {
                var style = jQuery.extend({}, Yxcm.Map.Style.line, currentMap.lineBrush.style);
                var lineMarker = currentMap.addMarker({ type: 'line', coordinates: currentMap.mouseClickTrack, style: style });
                //            var pointMarker = Yxcm.map.Current.addPointMarker({ coordinate: Yxcm.map.Current.mouseClickTrack[0], style: Yxcm.Map.Style.point });
                //            pointMarker.relationalMarker = lineMarker;
                currentMap.endDraw();
                currentMap.notifyEvent('endDrawMarker', { sender: this, marker: lineMarker });
                jQuery(currentMap.maplet.mapmask).unbind('mousemove.draw');
            }
        },

        area: {
            onsuccess: function() {
                var style = jQuery.extend({}, Yxcm.Map.Style.area, currentMap.areaBrush.style);
                var areaMarker = currentMap.addMarker({ type: 'area', coordinates: currentMap.mouseClickTrack, style: style });
                currentMap.endDraw();
                currentMap.notifyEvent('endDrawMarker', { sender: this, marker: areaMarker });
                jQuery(currentMap.maplet.mapmask).unbind('mousemove.draw');
            }
        }
    },

    Yxcm.Map.Map.superclass.constructor.apply(this, arguments);
}

Yxcm.extend(Yxcm.Map.Map, Yxcm.Event, {

    initialize: function(config) {
        this.config = config;
        this.maplet = new RMap(config.left, config.top, config.width, config.height, config.lat, config.lng, config.zoom, IMG_SERVER + '/rt/mapdb');
        this.maplet.addListener(this, 'onclicked');
        jQuery(config.container).append(this.maplet.get());
        this.maplet.getCenterByPoints = function(latlngs) {
            var lat = 0;
            var lng = 0;
            for (var i = 0; i < latlngs.length; i++) {
                lat += latlngs[i].lat;
                lng += latlngs[i].lng;
            }
            lat = Math.round((lat / latlngs.length) * 100000) / 100000;
            lng = Math.round((lng / latlngs.length) * 100000) / 100000;
            return new RLatLng(lat, lng);
        }
    },

    show: function() {
        this.maplet.show();
        toolbox = this.maplet.getToolBox(JS_SERVER + '/rapi/rwidget/rmap/toolbox/');
        toolbox.addCross();
        toolbox.addZoomBar();
        toolbox.addPan();
        jQuery(this.maplet.get()).pngFix();
        //        jQuery(this.maplet.markerdiv).attr('id', 'MarkerDiv').css('z-index', 100);
    },

    setAutoScroll: function(t) {
        if (t) {
            jQuery(this.maplet.mapmask).bind('mousemove.onAutoMove', Yxcm.setScope(this.onAutoScroll, this));
        } else {
            jQuery(this.maplet.mapmask).unbind('mousemove.onAutoMove');
        }
    },

    getMouseCoordinate: function() {
        var bounds = getBoundingClientRect(this.maplet.get().parentElement || this.maplet.get().parentNode);
        var left = this.maplet.mouseX - bounds.left;
        var top = this.maplet.mouseY - bounds.top;
        return this.getCoordinateByPoint(left, top);
    },

    getCoordinateByPoint: function(left, top) {
        return this.maplet.getLatLng(left, top);
    },

    getPointByCoordiate: function(coordinate) {
        return this.maplet.getPixel(coordinate.lat, coordinate.lng);
    },

    getCenterCoordinate: function() {
        return this.maplet.getCenter();
    },

    getCenterPoint: function() {
        var coor = this.getCenterCoordinate();
        return this.maplet.getPixel(coor.lat, coor.lng);
    },

    enableContextMenu: function() {
        jQuery(this.maplet.mapmask).contextMenu({ menu: this.contextMenu, noStopPropagation: true }, Yxcm.setScope(this.onContextMenu, this));
        jQuery(this.maplet.mapmask).enableContextMenu();
    },

    disableContextMenu: function() {
        jQuery(this.maplet.mapmask).disableContextMenu();
    },

    clearMouseClickTrack: function() {
        this.mouseClickTrack = [];
    },

    removeMarker: function(target) {
        if (typeof (target) == 'string' || typeof (target) == 'number') {
            target = this.findMarker(target);
        }

        if (target != null) {
            this.notifyEvent('beforeRemoveMarker', { sender: this, marker: target });
            var arr = [];
            for (var i = 0; i < this.markers.length; i++) {
                if (this.markers[i] != target) {
                    arr.push(this.markers[i]);
                }
            }
            this.markers = arr;
            this.notifyEvent('afterRemoveMarker', { sender: this, marker: target });
        }
    },

    findMarker: function(id) {
        for (var i = 0; i < this.markers.length; i++) {
            if (this.markers[i].id && this.markers[i].id == id && this.markers[i].type == 'point') {
                return this.markers[i];
            }
        }
        return null;
    },

    findShowingMarker: function() {
        for (var i = 0; i < this.markers.length; i++) {
            if (this.markers[i].detailIsShowing) {
                return this.markers[i];
            }
        }
        return null;
    },

    moveTo: function(coordinate) {
        this.maplet.smoothMoveWithoutEvents(coordinate.lat, coordinate.lng);
    },

    beginDraw: function() {
        this.notifyEvent('beginDraw', null);
        jQuery(document).bind('keypress.onCancelDraw', Yxcm.setScope(this.onCancelDraw, this));
        this.isDrawing = true;
        this.isMouseClickTrack = true;
        if (this.lineBrush) {
            this.lineBrush.turnoff();
            this.lineBrush.clear();
        }

        if (this.areaBrush) {
            this.areaBrush.turnoff();
            this.areaBrush.clear();
        }
    },

    beginDrawLine: function(setting) {
        this.beginDraw();

        if (!this.lineBrush) {
            this.lineBrush = new RPathTool(document.getElementById(setting.elementId));
            this.lineBrush.setMaplet(this.maplet);
            this.lineBrush.Parent = this.tempEventObj;
            this.lineBrush.addListener(this.eventListener.line, 'onsuccess');
        }

        this.setAutoScroll(true);
        this.brushType = 'line';
        this.lineBrush.style = setting.style;
        this.lineBrush.turnon();
    },

    beginDrawArea: function(setting) {
        this.beginDraw();

        if (!this.areaBrush) {
            this.areaBrush = new RPolygonTool(document.getElementById(setting.elementId));
            this.areaBrush.setMaplet(this.maplet);
            this.areaBrush.Parent = this.tempEventObj;
            this.areaBrush.addListener(this.eventListener.area, 'onsuccess');
        }

        if (setting && setting.style) {
            this.areaBrush.style = setting.style;
        }

        this.setAutoScroll(true);
        this.brushType = 'area';
        this.areaBrush.turnon();
    },

    endDraw: function() {
        this.cancelDraw();
        this.maplet.refreshStaticMarkers();
        this.maplet.refreshMarkers();
    },

    cancelDraw: function() {
        switch (this.brushType) {
            case 'line':
                this.lineBrush.turnoff();
                this.lineBrush.clear();
                break;
            case 'area':
                this.areaBrush.turnoff();
                this.areaBrush.clear();
                break;
        }
        this.isDrawing = false;
        this.isMouseClickTrack = false;
        this.clearMouseClickTrack();
        this.setAutoScroll(false);
        this.brushType = '';
        jQuery(document).unbind('keypress.cancelDraw');
        jQuery(map.maplet.mapmask).unbind('mousemove.draw');
    },

    addMarker: function(setting) {
        var result = null;
        setting.map = this;
        switch (setting.type) {
            case 'point':
                result = new Yxcm.Map.PointMarker(setting);
                break;
            case 'line':
                result = new Yxcm.Map.LineMarker(setting);
                break;
            case 'area':
                result = new Yxcm.Map.AreaMarker(setting);
                break;
        }

        result.registerEvent('beforeShowDetail', function(eventArg) {
            for (var i = 0; i < currentMap.markers.length; i++) {
                jQuery(currentMap.markers[i].marker.div).css('z-index', 1000);
                if (currentMap.markers[i].detailIsShowing) {
                    currentMap.markers[i].clearDetail();
                }
            }
        });
        this.markers.push(result);
        if (setting.type == 'line') {
            setting.type = 'point';
            var m = this.addMarker(setting);
            m.referenceMarker = result;
            this.markers.push(m);
            result.clickableMarker = m;
        } else if (setting.type == 'area') {
            setting.type = 'point';
            setting.coordinates = [this.maplet.getCenterByPoints(setting.coordinates)];
            var m = this.addMarker(setting);
            m.referenceMarker = result;
            this.markers.push(m);
            result.clickableMarker = m;
        }
        return result;
    },

    destroyAllMarkers: function() {
        for (var i = 0; i < this.markers.length; i++) {
            this.markers[i].destroy();
        }
        this.markers = [];
        this.maplet.clearMarkers();
        this.maplet.clearStaticMarkers();
    },

    hideAllMarkers: function() {
        for (var i = 0; i < this.markers.length; i++) {
            this.markers[i].hide();
        }
    },

    showAllMarkers: function() {
        for (var i = 0; i < this.markers.length; i++) {
            this.markers[i].show();
        }
    },

    refresh: function() {
        this.maplet.refreshStaticMarkers();
        this.maplet.refreshMarkers();
    },

    showMarkerDetail: function(marker) {
        this.activeMarker = marker;
        this.activeMarker.showDetail();
    },

    showMaxBounds: function() {
        var coordinates = [];
        for (var i = 0; i < this.markers.length; i++) {
            if (this.markers[i].type == 'point') {
                coordinates.push(this.markers[i].coordinate);
            } else {
                for (var j = 0; j < this.markers[i].coordinates.length; j++) {
                    coordinates.push(this.markers[i].coordinates[j]);
                }
            }
        }
        this.maplet.setMaxBoundsByLatLngs(coordinates);
    },

    beginDragMarker: function(marker) {
        jQuery(marker.marker.img).draggable();
    },

    onCancelDraw: function(event) {
        if (event.keyCode == '27') {
            this.cancelDraw();
        }
    },

    onAutoScroll: function(event) {
        var point = Yxcm.Util.getMousePoint(event);
        var centerPoint = this.getCenterPoint();
        if (point.x < 30) {
            centerPoint.left -= 100;
            var latlng = this.maplet.getLatLng(centerPoint.left, centerPoint.top);
            this.moveTo(latlng);
        } else if (point.x > (this.maplet.width - 30)) {
            centerPoint.left += 100;
            var latlng = this.maplet.getLatLng(centerPoint.left, centerPoint.top);
            this.moveTo(latlng);
        } else if (point.y < 30) {
            centerPoint.top -= 100;
            var latlng = this.maplet.getLatLng(centerPoint.left, centerPoint.top);
            this.moveTo(latlng);
        } else if (point.y > (this.maplet.height - 30)) {
            centerPoint.top += 100;
            var latlng = this.maplet.getLatLng(centerPoint.left, centerPoint.top);
            this.moveTo(latlng);
        }
    },

    onclicked: function() {
        if (this.isMouseClickTrack) {
            var bounds = getBoundingClientRect(this.maplet.get().parentElement || this.maplet.get().parentNode);
            var left = this.maplet.mouseX - bounds.left;
            var top = this.maplet.mouseY - bounds.top;
            var latlng = this.maplet.getLatLng(left, top);
            this.mouseClickTrack.push(latlng);
        }

        if (this.brushType == 'point') {
            var pointMarker = this.addMarker({ type: 'point', coordinates: [this.mouseClickTrack[0]], style: Yxcm.Map.Style.point });
            this.endDraw();
            this.notifyEvent('endDrawMarker', { sender: pointMarker });
        }
    },

    onContextMenu: function(action, el, pos) {
        this.notifyEvent('clickContextMenu', { action: action, sender: this, position: pos });
    }
});